// http.ts - 网络请求封装模块

// 接口请求前缀
let BASE_URL = "";

if (process.env.NODE_ENV === "development") {
  BASE_URL = "http://192.168.2.122:9898";
  //BASE_URL = "http://10.0.2.2:9898"; 
} else {
  BASE_URL = "https://www.xxx.com";
}

// 默认配置
const defaultConfig = {
  url: '',
  method: 'GET',
  data: {},
  header: {
    'Content-Type': 'application/json'
  },
  loading: true, // 是否显示加载提示
  retry: 0, // 请求失败重试次数
  isAuth: true // 是否需要携带token
}

interface RequestConfig {
  url: string;
  method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
  data?: Record<string, string|number|object>;
  header?: Record<string, string>;
  loading?: boolean;
  retry?: number;
  isAuth?: boolean;
}

interface ResponseData<T> {
  code: number;
  data: T;
  message: string;
}

type HybirdType = string|number|object;
type HttpResType = {statusCode:number,data:object};
// 请求拦截器
const requestInterceptor = (config: Partial<RequestConfig>): RequestConfig => {
  // 添加全局header（如token）
  if (config.isAuth) {
    const token = uni.getStorageSync('token')
    if (token) {
      config.header = {
        ...config.header,
        Authorization: `Bearer ${token}`
      }
    }
  }

  // 显示加载提示
  if (config.loading) {
    uni.showLoading({ title: '加载中...', mask: true })
  }

  return config;
}

// 响应拦截器
const responseInterceptor = <T>(response: Partial<HybirdType>): Promise<T> => {
  // 关闭加载提示
  if (defaultConfig.loading) {
    uni.hideLoading()
  }

  // 统一处理响应数据格式
  const { statusCode, data }:HttpResType = response as HttpResType;
  if (statusCode === 200) {
    const responseData = data as ResponseData<T>;
    if (responseData.code === 1) {
      return Promise.resolve(responseData.data);
    } else {
      return Promise.reject(responseData.message)
    }
  } else {
    return Promise.reject(`HTTP错误 ${statusCode}`)
  }
}

// 核心请求方法
const request = <T>(customConfig: RequestConfig): Promise<T> => {
  // 合并配置
  const config = { ...defaultConfig, ...customConfig }
  config.url = config.url.startsWith('http') ? config.url : BASE_URL + config.url

  // 执行请求拦截
  const finalConfig = requestInterceptor(config);

  return new Promise((resolve, reject) => {
    const requestTask = uni.request({
      ...finalConfig,
      success: (res: object) => {
        responseInterceptor<T>(res)
          .then((data) => {
            resolve(data);
          })
          .catch(reject)
      },
      fail: (err: HybirdType) => {
        // 关闭加载提示
        if (finalConfig.loading) uni.hideLoading()
        // 错误处理
        handleError(err, finalConfig, requestTask)
          .then(resolve)
          .catch(reject)
      },
      complete: () => {
        if (finalConfig.loading) uni.hideLoading();
      }
    })
  })
}

// 错误处理
const handleError = (err:HybirdType, config: RequestConfig, requestTask: HybirdType): Promise<any> => {
  return new Promise((resolve, reject) => {
    // 网络错误处理
    if (err?.errMsg.includes('request:fail')) {
      uni.showToast({
        title: '网络连接失败',
        icon: 'none',
        duration: 2000
      })
      return reject(err)
    }

    // HTTP状态码处理
    switch (err?.statusCode) {
      case 401:
        uni.navigateTo({ url: '/pages/login/login' })
        reject('登录已过期，请重新登录')
        break
      case 403:
        uni.showToast({ title: '无访问权限', icon: 'none' })
        reject('无访问权限')
        break
      case 500:
        uni.showToast({ title: '服务器错误', icon: 'none' })
        reject('服务器内部错误')
        break
      default:
        reject(err.message || '未知错误')
    }
  })
}

// 封装常用方法
interface HttpHelper {
  get<T>(url: string, data?: Record<string, any>, config?: Partial<RequestConfig>): Promise<T>;
  post<T>(url: string, data?: Record<string, any>, config?: Partial<RequestConfig>): Promise<T>;
  put<T>(url: string, data?: Record<string, any>, config?: Partial<RequestConfig>): Promise<T>;
  delete<T>(url: string, config?: Partial<RequestConfig>): Promise<T>;
}

const httpHelper: HttpHelper = {
  get: <T>(url: string, data?: Record<string, HybirdType>, config?: Partial<RequestConfig>) => 
    request<T>({ url, data, method: 'GET', ...config }),
  post: <T>(url: string, data?: Record<string, HybirdType>, config?: Partial<RequestConfig>) => 
    request<T>({ url, data, method: 'POST', ...config }),
  put: <T>(url: string, data?: Record<string, HybirdType>, config?: Partial<RequestConfig>) => 
    request<T>({ url, data, method: 'PUT', ...config }),
  delete: <T>(url: string, config: Partial<RequestConfig> = {}) => 
    request<T>({ url, method: 'DELETE', ...config })
}

export default httpHelper